package com.net.xpay.notify.service;

import com.alipay.api.msg.AlipayMsgClient;
import com.alipay.api.msg.MsgHandler;
import com.google.gson.JsonObject;
import com.net.common.exception.BusinessException;
import com.net.xpay.common.domain.UserShard;
import com.net.xpay.common.helper.NoticeHelper;
import com.net.xpay.common.manager.UserShardManager;
import com.net.xpay.core.CoreProperties;
import com.net.xpay.core.enums.PayTransBatchStatus;
import com.net.xpay.core.service.PayTransBatchService;
import com.net.xpay.core.utils.GsonUtil;
import com.net.shard.ShardUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

@Slf4j
@Service
public class AlipayMsgService extends Thread {

    @Autowired
    @Qualifier(value = "xpayAlipayMsgClient")
    private AlipayMsgClient alipayMsgClient;

    @Autowired
    private PayTransBatchService payTransBatchService;

    @Autowired
    private NoticeHelper noticeHelper;

    @Autowired
    private UserShardManager userShardManager;

    @Autowired
    private CoreProperties coreProperties;

    @Override
    public void run() {
        //不用接收消息
        if (coreProperties.getDisableAlipayClient() != null && coreProperties.getDisableAlipayClient() == 1) {
            return;
        }
        alipayMsgClient.setMessageHandler(new MsgHandler() {
            /**
             * 客户端接收到消息后回调此方法
             *  @param  msgApi 接收到的消息的消息api名
             *  @param  msgId 接收到的消息的消息id
             *  @param  bizContent 接收到的消息的内容，json格式
             */
            public void onMessage(String msgApi, String msgId, String bizContent) {
                log.info("receive message. msgApi:{}|msgId:{}|bizContent:{}", msgApi , msgId, bizContent);
                if ("alipay.fund.batch.order.changed".equals(msgApi)) {
                   processOrderChangeMsg(bizContent);
                }
            }
        });
        try {
            alipayMsgClient.connect();
        } catch (InterruptedException e) {
            log.error("alipayMsgService connect error", e);
            return;
        }
    }

    private void processOrderChangeMsg(String bizContent) {
        //支付订单状态发生改变
        JsonObject bizObj = GsonUtil.parse(bizContent).getAsJsonObject();
        String batchStatus = bizObj.get("batch_status").getAsString();
        if (!PayTransBatchStatus.isFinalStatus(PayTransBatchStatus.of(batchStatus))) {
            log.info("processOrderChangeMsg not final status|bizContent={}", bizContent);
            return;
        }
        //外部批次号
        String outBatchNo = bizObj.get("out_batch_no").getAsString();
        //批量转账批次号标准格式  10018-1111111111
        if (!outBatchNo.contains("-")) {
            return;
        }
        String[] contents = outBatchNo.split("-");
        if (contents.length != 2) {
            return;
        }
        long userId;
        long summaryId;
        try {
            userId = Long.parseLong(contents[0]);
            summaryId = Long.parseLong(contents[1]);
        } catch (Exception e) {
            log.info("parse contents failed|bizContent={}", bizContent, e);
            return;
        }

        UserShard userShard = userShardManager.getById(userId);
        //异常失败重试10秒
        LocalDateTime deadline = LocalDateTime.now().plusSeconds(10L);
        while (LocalDateTime.now().isBefore(deadline)) {
            try {
                ShardUtil.setShardContext(userShard.getShardId());
                payTransBatchService.updatePayTransBatch(userId, summaryId);
            } catch (Exception e) {
                log.warn("update payTransBatch failed|bizContent={}", bizContent, e);
                if (!(e instanceof BusinessException)) {
                    continue;
                }
            } finally {
                ShardUtil.cleanShardContext();
            }
            return;
        }
        log.warn("processOrderChangeMsg failed|bizContent={}", bizContent);
        if (PayTransBatchStatus.DISUSE.equals(PayTransBatchStatus.of(batchStatus))) {
            noticeHelper.sendSystemInfoNotice("【通知】支付宝批次推送支付结果处理失败|outBatchNo=" + outBatchNo, "text");
        } else {
            noticeHelper.sendSystemMonitorNotice("【警告】支付宝批次推送支付结果处理失败|outBatchNo=" + outBatchNo, "text");
        }

        throw new RuntimeException("failed");
    }
}
